<?php

/**
 * MySQL的连接类，该类可以连接mysql数据
 * 并实现其单例模式
 * 该类的功能还能够完成如下基本mysql操作：
 * 执行普通的增删改非返回结果集的语句
 * 执行select语句并可以返回3种类型的数据：
 * 多行结果（二维数组），单行结果（一维数组）
 */
class MySQLDB implements I_DAO {

    private $host;
    private $port;
    private $username;
    private $password;
    private $charset;
    private $dbname;

    private static $instance;

    private $resource;

    public static function getInstance($config)
    {
        if(!isset(self::$instance)) {
            self::$instance = new self($config);
        }
        return self::$instance;
    }

    private function __construct($config)
    {
        //初始化数据
        $this->host = isset($config['host']) ? $config['host'] : 'localhost';
        $this->port = isset($config['port']) ? $config['port'] : '3306';
        $this->username = isset($config['username']) ? $config['username'] : 'root';
        $this->password = isset($config['password']) ? $config['password'] : '';
        $this->charset = isset($config['charset']) ? $config['charset'] : 'utf8';
        $this->dbname = isset($config['dbname']) ? $config['dbname'] : '';

        //连接数据库
        $this->connect();
        //设置连接编码
        $this->setCharset($this->charset);
        //选定数据库
        $this->selectDb($this->dbname);
    }

    /**
     * 禁止克隆
     */
    private function __clone(){}

    private function connect()
    {
        $this->resource = mysql_connect("$this->host:$this->port", "$this->username", "$this->password") or die("连接数据库失败!");
    }

    public function setCharset($charset){
        mysql_set_charset($charset, $this->resource);
    }

    public function selectDB($dbname) {
        mysql_select_db($dbname, $this->resource);
    }


    /**
     * 执行最基本的sql语句功能
     * @param string $sql sql语句
     * 返回：失败直接结束，如果成功返回结果
     * @return resource
     */
    public function query($sql)
    {
        if(!$result = mysql_query($sql, $this->resource)) {
            echo ("<br />执行失败。");
            echo "<br />失败的sql语句为：" . $sql;
            echo "<br />出错信息为：" . mysql_error();
            echo "<br />错误代号为：" . mysql_errno();
            die();
        }
        return $result;
    }

    /**
     * 功能：执行select语句，返回2维数组
     * @param string $sql select语句
     * @return array 查询结果的二维数组
     */
    public function getAll($sql)
    {
        $result = $this->query($sql);
        $arr = array();
        while($rec = mysql_fetch_assoc($result)) {
            $arr[] = $rec;
        }
        return $arr;
    }

    /**
     * 返回查询结果的一行数据
     * @param string $sql select语句
     * @return array|bool 一行结果，失败则返回false
     */
    public function getRow($sql)
    {
        $result = $this->query($sql);
        if($row = mysql_fetch_assoc($result)) {
            return $row;
        }
        return false;
    }

    /**
     * 返回查询结果的第一个数据（第一行第一列）
     * @param string $sql 查询语句
     * @return bool|string
     */
    public function getOne($sql)
    {
        $result = $this->query($sql);
        $row = mysql_fetch_row($result);

        if($result === false) {
            return false;
        }
        return $row[0];
    }

    /**
     * 获取上一步insert操作产生的id
     */
    public function getInsertId(){
        return mysql_insert_id($this->resource);
    }

    /**
     * 返回成功执行时，受影响的行数
     */
    public function getAffectRows(){
        return mysql_affected_rows($this->resource);
    }

    /**
     * 转义用户数据，防止SQL注入
     * @param $data string 待转换字符串
     * @return string 转换后的字符串
     */
    public function escapeOneString($data)
    {
        return "'" . mysql_real_escape_string($data, $this->resource) . "'";
    }

    /**
     * 转义数组内的全部元素
     * @param array $data
     * @return array
     */
    public function escapeAllString($data)
    {
        foreach ($data as $key => $value) {
            $data[$key] = $this->escapeOneString($value);
        }
        return $data;
    }
}